/**
 * Created by xiaoz on 16/8/13.
 * base组件，其他组件都基于该组件
 */
define(["utils"], function(utils) {

    var Component = function(config) {
        var _this = this;
        this.pageview = config.$$pageview || this;
        this.config = config;
        //组件key，赋值id
        this.id = this.pageview.config.pageKey + "_" + config.comKey;

        this.disabled = config.disabled || false;
        //组件结构tree，父级对象
        this.parent = config.$$parent;
        //绑定的数据源
        this.datasource = config.$$datasource || [];
        //处理复合组件引用
        this.rowInstance = config.$$rowInstance;
        //是否需要引用，ref为true表示该组件能在父级的refs对象中检索到组件
        if (config.ref) {
            if (this.rowInstance) {
                this.rowInstance.refs = this.rowInstance.refs || {};
                this.rowInstance.refs[config.comKey] = this;
            } else {
                this.pageview.refs[config.comKey] = this;
            }
        }
        var className = config.className || "";
        //当前组件根节点元素
        this.selectedClassName = config.selectedClassName||"yy-selected";
        config.tagName = config.tagName || "DIV";
        var activeClassName = config.activeClassName ? "data-activecn='" + config.activeClassName + "'" : "";
        //组件在dom中的引用，$el
        this.$el = $("<" + config.tagName + " " + activeClassName + " data-comname='" + config.comKey + "' class='" + className + "'></" + config.tagName + ">");
        //配置config，主要把绑定的数据提取到当前组件引用的值。
        config = this._processConfig(config);
        //处理符合组件，repeat和listview做特殊处理
        this.components = {};
        if (config.type == "repeat" || config.type == "listview") {
            this.components = [];
        }
        //调用页面controller的初始化方法
        var pluginName = this.config.comKey + "_init";
        if (this.pageview.plugin && this.pageview.plugin[pluginName]) {
            var method = this.pageview.plugin[pluginName];
            if (method) {
                method.call(this.pageview.plugin, this);
            }
        }

        if(this.config.type==="pageview"){
            // 实现拆分JSON的功能
            var children = this.config.children;
            if(children && children instanceof Array){
                for(var i=0,j=children.length;i<j;i++){
                    var childConfig = children[i].components;
                    if(childConfig){
                        for(var key in childConfig){
                            this.config.components[key] = utils.copy(childConfig[key]);
                        }
                    }
                }
            }
        }
        //渲染样式
        var style = config.style;
        if (!config.noNeedSetStyle) {
            if (style && config.type != "segment") {
                utils.css(this.$el, style);
            }
        }
        this.disabledClassName = config.disabledClassName || "yy-disabled";
        //使能
        if (this.disabled) {
            this.setDisabled(true);
        }
        //组件click事件处理
        if (config.comKey) {
            var method_name = config.comKey + "_click";
            var method_click = _this.pageview.plugin[method_name];
            if (method_click) {
                this.$el.bind("click", function(e) {
                    //取消该元素的默认事件，为了阻止浏览器对元素默认事件的响应
                    e.preventDefault();
                    //阻止浏览器事件机制继续往下传递
                    e.stopPropagation();
                    //响应注册在body层级的事件回调
                    _this.pageview.pageManager.triggerBodyClickWithoutSelf(_this.pageview);
                    //执行页面controller中的组件click方法
                    !_this.disabled && method_click && method_click.call(_this.pageview.plugin, _this, {
                        e: e
                    });
                });
            }
            var hover = config.comKey + "_hover";
            var method_hover = _this.pageview.plugin[hover];
            if(method_hover){
                this.$el.hover(function(e){
                    //取消该元素的默认事件，为了阻止浏览器对元素默认事件的响应
                    e.preventDefault();
                    //阻止浏览器事件机制继续往下传递
                    e.stopPropagation();
                    //响应注册在body层级的事件回调
                    _this.pageview.pageManager.triggerBodyClickWithoutSelf(_this.pageview);
                    //执行页面controller中的组件click方法
                    !_this.disabled && method_hover && method_hover.call(_this.pageview.plugin, _this, {
                        e: e,
                        type:"in"
                    });
                },function(e){
                    //取消该元素的默认事件，为了阻止浏览器对元素默认事件的响应
                    e.preventDefault();
                    //阻止浏览器事件机制继续往下传递
                    e.stopPropagation();
                    //响应注册在body层级的事件回调
                    _this.pageview.pageManager.triggerBodyClickWithoutSelf(_this.pageview);
                    //执行页面controller中的组件click方法
                    !_this.disabled && method_hover && method_hover.call(_this.pageview.plugin, _this, {
                        e: e,
                        type:"out"
                    });
                });
            }
        }
        //选择态开关
        if (config.isSelected === true) {
            this.selected();
        } else if (this.isSelected === false) {
            // this.UnSelected();
        }
    };
    //删除组件
    Component.prototype.remove = function() {
        if (this.config.ref) {
            if (this.rowInstance) {
                if (this.rowInstance.refs) {
                    delete this.rowInstance.refs[this.config.comKey];
                }

            } else {
                delete this.pageview.refs[this.config.comKey];
            }
        }
    };

    Component.prototype.setDisabled = function(disabled, isNoStyle) {
        if (this.config.alwaysEnable) {
            return;
        }

        this.disabled = disabled;
        if (isNoStyle !== true) {
            if (this.disabled) {
                this.$el.addClass(this.disabledClassName);
            } else {
                this.$el.removeClass(this.disabledClassName);
            }
        }
        if(this.components instanceof Array){
            for(var i=0,j=this.components.length;i<j;i++){
                this.components[i].setDisabled(this.disabled, isNoStyle);
            }
        }else{
            for (var key in this.components) {
                this.components[key].setDisabled(this.disabled, isNoStyle);
            }
        }


    };



    Component.prototype.addClass = function(className) {
        return this.$el.addClass(className);
    };

    //show菊花
    Component.prototype.showLoading = function(config) {
        config = config || {};
        var mode = config.mode || 1;
        this.loadingConfig = config;
        if (!config.timeout || isNaN(config.timeout)) {
            config.timeout = 7000;
        }
        if(this.loadingerrorWrapper){
            this.loadingerrorWrapper.remove();
        }
        this.loadingtimeout = parseInt(config.timeout) || 10000;
        var text = config.text || "正在加载,请耐心等待...";
        if (this.loadingWrapper) {
            this.loadingWrapper.remove();
            this.loadingWrapper = null;
        }
        this.loadingWrapper = $("<div class='yy-loading-wrap'></div>");
        if (config.style) {
            this.loadingWrapper.css(config.style);
        }
        var boxClass = "yy-loading-box-" + mode;
        this.loadingBox = $("<div class='" + boxClass + "'></div>");
        this.loading = $("<div class='yy-loading-box-icon'></div>");
        this.loadingText = $("<div class='yy-loading-box-text'>" + text + "</div>");
        this.loadingBox.append(this.loading).append(this.loadingText);
        this.loadingWrapper.append(this.loadingBox);
        var opts = {
            lines: 11 // The number of lines to draw
                ,
            length: 28 // The length of each line
                ,
            width: 14 // The line thickness
                ,
            radius: 42 // The radius of the inner circle
                ,
            scale: 0.2 // Scales overall size of the spinner
                ,
            corners: 1 // Corner roundness (0..1)
                ,
            color: config.loadingColor || this.pageview.pageManager.appConfig.loadingColor // #rgb or #rrggbb or array of colors
                ,
            opacity: 0.25 // Opacity of the lines
                ,
            rotate: 0 // The rotation offset
                ,
            direction: 1 // 1: clockwise, -1: counterclockwise
                ,
            speed: 1 // Rounds per second
                ,
            trail: 60 // Afterglow percentage
                ,
            fps: 20 // Frames per second when using setTimeout() as a fallback for CSS
                ,
            zIndex: 2000 // The z-index (defaults to 2000000000)
                ,
            className: 'spinner' // The CSS class to assign to the spinner
                ,
            top: '50%' // Top position relative to parent
                ,
            left: '50%' // Left position relative to parent
                ,
            shadow: false // Whether to render a shadow
                ,
            hwaccel: false // Whether to use hardware acceleration
                ,
            position: 'absolute' // Element positioning
        };
        try {
            this.loading.spin(config.loadingOpts || opts);
        } catch (e) {

        }
        this.$el.append(this.loadingWrapper);
        // this.startLoadingTimeout();
    };

    Component.prototype.startLoadingTimeout = function(config) {
        var _this = this;
        if (this.loadingTimeId) {
            window.clearTimeout(this.loadingTimeId);
            this.loadingTimeId = null;
        }
        this.loadingTimeId = window.setTimeout(function() {
            _this.hideLoading(false);
        }, this.loadingtimeout);
    };

    Component.prototype.showLoadError = function(reloadCallback) {
        var _this = this;
        var loadingErrorIconClass = this.pageview.pageManager.appConfig.ladingErrorIconClass || "yy-loading-error-icon";
        this.loadingerrorWrapper = $("<div class='yy-loading-error-wrap'></div>");
        if (this.loadingConfig.style) {
            this.loadingerrorWrapper.css(this.loadingConfig.style);
        }
        var icon = $("<div class='" + loadingErrorIconClass + "'></div>");
        var mess = $("<span class='yy-loading-error-mes'>加载失败,<span class='yy-loading-reload'>重新加载</span></span>");
        this.loadingerrorWrapper.append(icon).append(mess);
        mess.bind("click", function(e) {
            _this.loadingerrorWrapper.remove();
            _this.showLoading(_this.loadingConfig);
            reloadCallback();
        });
        this.$el.append(_this.loadingerrorWrapper);
    };

    Component.prototype.hideLoading = function(isSuccess) {
        this.loadingWrapper.remove();
        window.clearTimeout(this.loadingTimeId);
        this.loadingTimeId = null;
        if (isSuccess) {

        } else {
            if (this.loadingConfig) {
                var reloadCallback = this.loadingConfig.reloadCallback;
                if (reloadCallback) {
                    this.showLoadError(reloadCallback);
                }
            }

        }

    };


    Component.prototype.removeClass = function(className) {
        return this.$el.removeClass(className);
    };
    //检索出组件绑定的数据。
    Component.prototype._processConfig = function(config) {
        for (var key in config) {
            var key_arr = key.split("_");
            if (key_arr.length == 2 && key_arr[1] == "bind") {
                var value = config[key];
                var attrName = key_arr[0];
                var val_type = typeof(value);
                if (val_type == "string") {
                    config[attrName] = getValueByPath(this.datasource, value.split("."));
                } else if (val_type == "object") {
                    for (var key1 in value) {
                        var attrName1 = key1;
                        var bind_val = getValueByPath(this.datasource, value[key1].split("."));
                        // if(bind_val){
                        config[attrName] = config[attrName] || {};
                        config[attrName][attrName1] = bind_val;
                        // }
                    }
                }
            }
        }
        return config;
    };

    function getValueByPath(data, path) {
        if (!data) {
            return null;
        }
        var r = data;
        for (var i = 0, j = path.length; i < j; i++) {
            var pathkey = path[i];
            r = r[pathkey];
            if (!r && r != 0) {
                r = null;
                break;
            }
        }
        return r;
    }



    //选择态设置
    Component.prototype.selected = function(isFromParent) {
        if (this.disabled) {
            return;
        }
        if(isFromParent){
          if(this.config.disableParentSelect){
            return;
          }
        }

        this.isSelected = true;
        if(this.selectedClassName&&this.selectedClassName!==""){
          this.$el.addClass(this.selectedClassName);
        }

        this.afterSelected && this.afterSelected();
        for (var key in this.components) {
            this.components[key].selected(true);
        }

    };


    Component.prototype.unSelected = function(isFromParent) {
        if (this.disabled) {
            return;
        }
        if (isFromParent) {
            if (this.config.disableParentSelect) {
                return;
            }
        }
        this.afterUnSelected && this.afterUnSelected();
        this.isSelected = false;

        if (this.selectedClassName && this.selectedClassName !== "") {
            this.$el.removeClass(this.selectedClassName);
        }

        for (var key in this.components) {
            this.components[key].unSelected(true);
        }
    };

    Component.prototype.hide = function(){
        this.$el.hide();
    };

    Component.prototype.show = function(){
        this.$el.show();
    };

    // 从配置找到组件并实例化
    Component.prototype._prepareComponent = function(com_key, datasource, rowInstance) {
        // 通过组件key找到组件配置
        var com_config = utils.copy(this.pageview.config.components[com_key]);
        var com_type = com_config.type;
        // 组件原型
        var ComClass = utils.getComponentInstance(com_type);
        com_config.$$pageview = this.pageview;
        com_config.$$rowInstance = rowInstance;
        com_config.$$parent = this;
        com_config.comKey = com_key;
        com_config.$$datasource = datasource;
        // 实例化组件
        var com_instance = new ComClass(com_config, null);
        // 调用组件生命周期方法，didmount
        var pluginName = com_key + "_didmount";
        if (this.pageview.plugin) {
            var method = this.pageview.plugin[pluginName];
            if (method) {
                method.call(this.pageview.plugin, com_instance);
            }
        }
        // 触发页面设置的delegate事件
        if (this.pageview.componentsInitActions[com_key]) {
            this.pageview.componentsInitActions[com_key](com_instance);
            delete this.pageview.componentsInitActions[com_key];
        }
        // 如果是通过delegates添加的，走下面的回调
        var actions = this.pageview.componentsInitActionsArray[com_key];
        if(actions){
            while(actions.length > 0){
                var action = actions.pop();
                action(com_instance);
            }
            delete this.pageview.componentsInitActionsArray[com_key];
        }

        if (com_config.$$rowInstance) {
            if (com_config.$$rowInstance.componentsInitActions[com_key]) {
                com_config.$$rowInstance.componentsInitActions[com_key](com_instance);
                delete com_config.$$rowInstance.componentsInitActions[com_key];
            }
            var rowActions = com_config.$$rowInstance.componentsInitActionsArray[com_key];
            if(rowActions){
                while(rowActions.length > 0){
                    var rowAction = rowActions.pop();
                    rowAction(com_instance);
                }
                delete com_config.$$rowInstance.componentsInitActionsArray[com_key];
            }
        }
        return com_instance;
    };
    // 初始化组件
    Component.prototype._initComponents = function(config, datasource, customInitLayout, rowInstance) {
        for (var i = 0, j = config.root.length; i < j; i++) {
            var com_key = config.root[i];
            var com_instance = this._prepareComponent(com_key, datasource, rowInstance);
            if (config.isContainer || config.type == "repeat") {
                this.components.push = com_instance;
                customInitLayout(com_instance);
            } else if (config.type == "tabbarview") {
                this.components[com_key] = com_instance;
                customInitLayout(com_instance);
            } else {
                this.components[com_key] = com_instance;
            }
        }

        return this.components;
    };

    Component.prototype.getClientRect = function() {
        return this.$el[0].getBoundingClientRect();
    };


    Component.prototype.showSubmiting = function(config) {
        config = config || {};
        this.submitiongConfig = config;
        var isFullScreen = config.isFullScreen;
        //isFullScreen ? "yy-submiting-bk positionfixed" :
        var className1 = "yy-submiting-bk";
        //isFullScreen ? "yy-submiting-box positionfixed" :
        this.submitingBK = $("<div class='" + className1 + "'></div>");
        var className2 =  "yy-submiting-box";
        this.submitingBox = $("<div class='" + className2 + "'></div>");
        var opts = {
            lines: 11 // The number of lines to draw
                ,
            length: 28 // The length of each line
                ,
            width: 14 // The line thickness
                ,
            radius: 42 // The radius of the inner circle
                ,
            scale: 0.2 // Scales overall size of the spinner
                ,
            corners: 1 // Corner roundness (0..1)
                ,
            color: '#fff' // #rgb or #rrggbb or array of colors
                ,
            opacity: 0.25 // Opacity of the lines
                ,
            rotate: 0 // The rotation offset
                ,
            direction: 1 // 1: clockwise, -1: counterclockwise
                ,
            speed: 1 // Rounds per second
                ,
            trail: 60 // Afterglow percentage
                ,
            fps: 20 // Frames per second when using setTimeout() as a fallback for CSS
                ,
            zIndex: 2e9 // The z-index (defaults to 2000000000)
                ,
            className: 'spinner' // The CSS class to assign to the spinner
                ,
            top: '50%' // Top position relative to parent
                ,
            left: '50%' // Left position relative to parent
                ,
            shadow: false // Whether to render a shadow
                ,
            hwaccel: false // Whether to use hardware acceleration
                ,
            position: 'absolute' // Element positioning
        };
        this.submitingIconBox = $("<div class='yy-submiting-iconbox'></div>");
        this.submitingText = $("<div class='yy-submiting-text'>" + (config.text || "正在提交...") + "</div>");
        try {
            this.submitingIconBox.spin(opts);
        } catch (e) {

        }
        var classBox = isFullScreen ? "yy-submiting-box-wrap positionfixed" :"yy-submiting-box-wrap";
        this.submitingBoxWrap = $("<div class='"+classBox+"'></div>");
        var midspan = $("<span class='yy-mid-span'></span>");

        this.submitingBox.append(this.submitingIconBox).append(this.submitingText);
        this.submitingBoxWrap.append(this.submitingBox).append(midspan);
        this.$el.append(this.submitingBK).append(this.submitingBoxWrap);
    };

    Component.prototype.hideSubmiting = function(isSuccess,text) {
        var _this = this;
        try {
            this.submitingIconBox.spin(false);
        } catch (e) {

        }
        if (isSuccess) {
            if (this.submitiongConfig.successText === null) {
                _this.submitingBK.remove();
                _this.submitingBoxWrap.remove();
                return;
            }
            var successIconClass = this.submitiongConfig.successIconClass || "yy-successIconClass";
            this.submitingIconBox.addClass(successIconClass);
            if(text){
                this.submitingText.html(text);
            }else{
                this.submitingText.html(this.submitiongConfig.successText || "提交成功");
            }
        } else {
          if (this.submitiongConfig.errorText === null) {
              _this.submitingBK.remove();
              _this.submitingBoxWrap.remove();
              return;
          }
            var errorIconClass = this.submitiongConfig.errorIconClass || "yy-errorIconClass";
            this.submitingIconBox.addClass(errorIconClass);
            if(text){
                this.submitingText.html(text);
            }else{
                this.submitingText.html(this.submitiongConfig.errorText || "提交失败");
            }
        }
        window.setTimeout(function() {
            _this.submitingBK.remove();
            _this.submitingBoxWrap.remove();
        }, 1000);
    };


    //通过组件获取组件对象
    Component.prototype.getComponentInstanceByComKey = function(com_key, datasource, rowInstance, success, error) {
        var _this = this;

        this.loadFiles([com_key], this.pageview || this, function() {
            var com_instance = _this._prepareComponent(com_key, datasource, rowInstance);
            success(com_instance);
        }, function() {
            if (error) {
                error();
            }
        });
    };
    // 初始化布局
    Component.prototype.initLayout = function(datasource, customInitLayout, rowInstance, initSuccess) {
        var _this = this;
        if (this.config.root && this.config.root.length > 0) {
            this.loadFiles(this.config.root, this.pageview || this, function() {
                if (customInitLayout) {
                    _this._initComponents(_this.config, datasource, customInitLayout, rowInstance);
                } else {
                    _this._initComponents(_this.config, datasource, null, rowInstance);
                    for (var i = 0, j = _this.config.root.length; i < j; i++) {
                        var root = _this.$$childrenWrapper || _this.$el;
                        root.append(_this.components[_this.config.root[i]].$el);
                    }
                }

                initSuccess && initSuccess();

                if (_this.config.type == "pageview") {
                    var pageload = _this.plugin.onPageLoad;
                    window.setTimeout(function() {
                        pageload && pageload.call(_this.plugin, _this);
                    }, 66);
                }

            }, function() {

            });
        }

    };


    Component.prototype.loadFiles = function(comkey_arr, pageviewInstance, success, error) {
        var fileCount = comkey_arr.length,
            successCount = 0;
        var _this = this;
        for (var i = 0; i < fileCount; i++) {
            (
                function(_fileCount, index, com_name) {
                    var com_config = pageviewInstance.config.components[com_name];
                    if(com_config){
                        utils.getComponentClass(com_config, function(comClass) {
                            successCount += 1;
                            if (successCount == _fileCount) {

                                success();
                            }

                        }, function() {
                            error();
                        });
                    }else{
                        console.error("%s components not found in your page",com_name);
                        error();
                    }
                }
            )(fileCount, i, comkey_arr[i]);
        }
    };
    return Component;
});
